<?php
    if (!defined('ZT')) exit;

    class Plantilla {
        public static $parser_niveles;
        public static $parser_usando;
    
        static function compila($plantilla, $destino)
        {
            self::$parser_niveles = array(
                array('clave' => '', 'valor' => '$GLOBALS')
            );
        
            file_put_contents(
                $destino, 
                "<?php if (!defined('ZT')) exit; ?>\n".
                preg_replace_callback(
                    '/\$(?:{.*?}|[a-z_]\w*(?:->\w+)*)|<(?:\/(?:si|ciclo|cuenta|usando)|sino|si(?:no_si)? condicion=".*?"|(?:incluye|evalua|interpreta) archivo=".*?"|ejecuta script=".*?"|ciclo var=".*?"|cuenta var=".*?" desde=".*?" hasta=".*?" incremento=".*?"|usando var=".*?" aplicando=".*?"|php>[.\s]*?<\/php)>/i', 
                    'zt_parser', 
                    file_get_contents($plantilla)
                )
            );
        }
    }
    
    function zt_parser($res)
    {
        $res = $res[0];
 
        if ($res[0] === '$') {
            $c = $res[strlen($res) - 1];
            
            if ($c === '}') {
                return zt_expresion(substr($res, 2, -1));
            }
            else return zt_variable($res);
        }

        $res = substr($res, 1, -1);
        $c = $res[0];

        if ($c === '/') {
            $res[0] = 'f';
            $res = "zt_$res";
            
            return $res( );
        }
        else if ($c === 'p') {
            return "<?php\n".substr($res, 4, -6)."\n?>";
        }
               
        $espacio = strpos($res, ' ');

        if ($espacio !== false) {
            $funcion = 'zt_'.substr($res, 0, $espacio);
            return $funcion($res);
        }
        else {
            $funcion = "zt_$res";
            return $funcion( );
        }
    }

    
    function zt_php( )
    {
        return '<?php';
    }
    
    function zt_fphp( )
    {
        return '?>';
    }
    
    function zt_si($texto)
    {
        return '<?php if ('.zt_sustitucion_expresion(substr($texto, 14, -1)).') { ?>';
    }

    function zt_sino_si($texto)
    {
        return '<?php } else if ('.zt_sustitucion_expresion(substr($texto, 19, -1)).') { ?>';
    }
    
    function zt_sino( )
    {
        return '<?php } else { ?>';
    }
    
    function zt_fsi( )
    {
        return '<?php } ?>';
    }
    
    function zt_ciclo($texto)
    {
        $variable = zt_sustitucion_expresion(substr($texto, 11, -1));
        $nivel = count(Plantilla::$parser_niveles);
        
        $clave = "\$index$nivel";
        $valor = "\$actual$nivel";
        
        Plantilla::$parser_niveles[] = array('clave' => $clave, 'valor' => $valor);

        return "<?php foreach ($variable as $clave => $valor) { ?>";
    }
    
    function zt_fciclo( )
    {
        array_pop(Plantilla::$parser_niveles);
        return '<?php } ?>';
    }
    
    function zt_cuenta($texto)
    {
        $pvar = strpos($texto, '"') + 1;
        $fvar = strpos($texto, '"', $pvar);
        
        $nombre_contador = substr($texto, $pvar, $fvar - $pvar);
        
        $pvar = strpos($texto, '"', $fvar + 1) + 1;
        $fvar = strpos($texto, '"', $pvar);

        $desde = zt_sustitucion_expresion(substr($texto, $pvar, $fvar - $pvar));
        
        $pvar = strpos($texto, '"', $fvar + 1) + 1;
        $fvar = strpos($texto, '"', $pvar);

        $hasta = zt_sustitucion_expresion(substr($texto, $pvar, $fvar - $pvar));
    
        $pvar = strpos($texto, '"', $fvar + 1) + 1;
        $fvar = strpos($texto, '"', $pvar);

        $incremento = substr($texto, $pvar, $fvar - $pvar);
    
        return "<?php for (\$$nombre_contador = $desde, \$tope$nombre_contador = $hasta; \$$nombre_contador != \$tope$nombre_contador; \$$nombre_contador += $incremento) { ?>";	
    }
    
    function zt_fcuenta( )
    {
        return '<?php } ?>';
    }
    
    function zt_usando($texto)
    {
        $pvar = strpos($texto, '"') + 1;
        $fvar = strpos($texto, '"', $pvar);
        
        $variable = zt_sustitucion_variable(substr($texto, $pvar, $fvar - $pvar));
        
        $pvar = strpos($texto, '"', $fvar + 1) + 1;
        $fvar = strpos($texto, '"', $pvar);

        $aplicando = zt_sustitucion_expresion(substr($texto, $pvar, $fvar - $pvar));
        
        $var_id = '$zt_usando'.count(Plantilla::$parser_usando);
        Plantilla::$parser_usando[] = $variable;

        return "<?php $var_id = $variable; $variable = ".str_replace('?', $var_id, $aplicando).'; ?>';
    }
    
    function zt_fusando( )
    {
        $num_id = count(Plantilla::$parser_usando) - 1;
        $variable = array_pop(Plantilla::$parser_usando);
        
        return "<?php $variable = \$zt_usando$num_id; ?>";
    }
    
    function zt_incluye($texto)
    {
        return '<?php readfile(\''.RAIZ.'plantillas/'.substr($texto, 17, -1).'\'); ?>';
    }
    
    function zt_evalua($texto)
    {
        $ruta = substr($texto, 16, -1);
        return '<?php zt_muestra_html(\''.RAIZ."plantillas/$ruta', '".RAIZ."cache/$ruta'); ?>";
    }

    function zt_interpreta($texto)
    {
        return '<?php require_once(\''.RAIZ.substr($texto, 20, -1).'\'); ?>';
    }
    
    function zt_ejecuta($texto)
    {
        return '<?php Main::ejecuta(\''.RAIZ.substr($texto, 16, -1).'\'); ?>';
    }
    
    function zt_variable($variable)
    {
        return '<?php echo '.zt_sustitucion_variable($variable).'; ?>';
    }
    
    function zt_expresion($expresion)
    {
        return '<?php echo '.zt_sustitucion_expresion($expresion).'; ?>';
    }
        
    function zt_sustitucion_expresion($expresion)
    {
        return preg_replace_callback('/\$[_a-z]\w*(?:->\w+)*/i', 'zt_sustitucion_variable_callback', $expresion);
    }
    
    function zt_sustitucion_variable_callback($variable)
    {
        return zt_sustitucion_variable($variable[0]);
    }
    
    function zt_sustitucion_variable($variable)
    {
        end(Plantilla::$parser_niveles);
    
        if ($variable === '$RAIZ') {
            return 'TPL_RAIZ';
        }

        $partes = explode('->', substr($variable, 1));
        
        if ($partes[0] === 'CONTADOR') {
            return "\${$partes[1]}";
        }
        
        $construida = ''; 
 
        foreach ($partes as $var) {
		    if ($var === 'GLOBAL') {
			    reset(Plantilla::$parser_niveles);
			}
            else if ($var === 'PADRE') {
			    prev(Plantilla::$parser_niveles);
			}
            else if ($var === 'CLAVE') {
                $temp = current(Plantilla::$parser_niveles);
                return $temp['clave'];
            }
            else if ($var !== 'ACTUAL') {
                $construida .= "['$var']";
			}
        }
		
        $temp = current(Plantilla::$parser_niveles);
        return $temp['valor'].$construida;
    }
?>